/********************************************
 * Joe Helgeson
 * CS362 Assignment 4
 * randomtestadventurer.c
 *******************************************/

#include <assert.h>
#include "dominion.h"
#include "dominion_helpers.h"
#include <math.h>
#include "rngs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// set NOISY_TEST to 0 to remove printfs from output
#define NOISY_TEST 1

//enabling debugging messages to appear
//#ifdef DEBUG
//#undef DEBUG
//#endif
//#define DEBUG 1

#define NUM_TESTS 500 //arbitrary number -- feel free to change

void testIt(struct gameState* tState);

///////////////////////////////////////
int main(int argc, char const** argv) {
	struct gameState* tState = malloc(sizeof(struct gameState));
	testIt(tState);
	free(tState);
	return 0;
}

///////////////////////////////////////
void testIt(struct gameState* tState) {

/* personal notes (ignore): 
 int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed, struct gameState *state)
 int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus)
*/

	//general initial game setup
	srand(time(NULL));
	int numPlayers = rand() % 3 + 1;
	int kingdomCards[10]; 
	int i;
	for (i=0; i<10; i++){
		kingdomCards[i] = (i+7); //set kingdom cards to be from adventurer onward
	}

	//setup for card under test
	int player;  //assigned differently each test
	int handPos = 0;
	int card = adventurer;

	//hand treasure card counters
	int hTreasCardCount = 0; //# treasure cards in player's hand
	int hCoppCount = 0; int hSilvCount = 0; int hGoldCount = 0;
	int nhTreasCardCount = 0; //# treasure cards in player's NEW hand (after playing adventurer)
	int nhCoppCount = 0; int nhSilvCount = 0; int nhGoldCount = 0;

	//deck treasure card counters
	int dTreasCardCount = 0; //# treasure cards in player's deck
	int dCoppCount = 0; int dSilvCount = 0; int dGoldCount = 0;
	int ndTreasCardCount = 0; //# treasure cards in player's NEW deck (after playing adventurer)
	int ndCoppCount = 0; int ndSilvCount = 0; int ndGoldCount = 0;

	//hand and deck contents backups
	int origHandContents[MAX_HAND] = {0};
	int origDeckContents[MAX_DECK] = {0};
	int origHandSize; 
	int origDeckSize;
	int newHandSize;
	int newDeckSize; 

	//stuff needed to call cardEffect()
	int choice1 = 0; //irrelevant for this card
	int choice2 = 0; //irrelevant for this card
	int choice3 = 0; //irrelevant for this card
	int bonusval = 0; //irrelevant for this card
	int* bonus = &bonusval; //irrelevant for this card
	
	//misc
	int randomSeed; //arbitrary num for various dominion functions
	
	//Top o' the testing loop
	int t, d, h; //counters for (t)est, (d)eck, and (h)and iterations, respectively
	for (t=0; t<NUM_TESTS; t++) {

		//initialize a game (but doesn't create a discard pile)
		randomSeed = ((rand() % 3) + 1); 
		initializeGame(numPlayers, kingdomCards, randomSeed, tState);

		//init hand and deck treasure card counters
		hTreasCardCount = 0; hCoppCount = 0; hSilvCount = 0; hGoldCount = 0;
		dTreasCardCount = 0; dCoppCount = 0; dSilvCount = 0; dGoldCount = 0;
		nhTreasCardCount = 0; nhCoppCount = 0; nhSilvCount = 0; nhGoldCount = 0;
		ndTreasCardCount = 0; ndCoppCount = 0; ndSilvCount = 0; ndGoldCount = 0;

		//pick a player
		player = rand() % numPlayers;

	//RANDOMIZE PLAYER'S HAND:
		//randomize hand size, then store backup
		tState->handCount[player] = rand() % MAX_HAND;
		if (tState->handCount[player] == 0) { //need at least 1 card in a hand
			tState->handCount[player] = 1;
		}
		origHandSize = tState->handCount[player];

		//randomize hand contents
		for (h=0; h<origHandSize; h++) {
			//randomly fill hand...
			tState->hand[player][h] = rand() % 27; 
		//count the treasure cards in it...
			if (tState->hand[player][h] == copper) {
				hTreasCardCount++;
				hCoppCount++;
			} else if (tState->hand[player][h] == silver) {
				hTreasCardCount++;
				hSilvCount++;
			} else if (tState->hand[player][h] == gold) {
				hTreasCardCount++;
				hGoldCount++;
			}
		}
		//store hand contents backup
		for (h=0; h<origHandSize; h++) {
			origHandContents[h] = tState->hand[player][h];
		}

	//RANDOMIZE PLAYER'S DECK:
		//randomize deck size, then store backup
		tState->deckCount[player] = rand() % MAX_DECK; //includes empty deck
		origDeckSize = tState->deckCount[player];

		//randomize deck contents
		for (d=0; d<origDeckSize; d++) {
			//randomly fill deck...
			tState->deck[player][d] = rand() % 27; 
		//count the treasure cards in it...
			if (tState->deck[player][d] == copper) {
				dTreasCardCount++;
				dCoppCount++;
			} else if (tState->deck[player][d] == silver) {
				dTreasCardCount++;
				dSilvCount++;
			} else if (tState->deck[player][d] == gold) {
				dTreasCardCount++;
				dGoldCount++;
			}
		}
		//store deck contents backup
		for (d=0; d<origDeckSize; d++) {
			origDeckContents[d] = tState->deck[player][d];
		}


	////////TEST CARD #7 (adventurer)
		printf("With a %d card hand with %d C, %d S, %d G,\n", origHandSize, hCoppCount, hSilvCount, hGoldCount);
		printf(" and a %d card deck with %d C, %d S, %d G:\n", origDeckSize, dCoppCount, dSilvCount, dGoldCount);
		cardEffect(card, choice1, choice2, choice3, tState, handPos, bonus);

	//POST-PLAY comparisons
		newHandSize = tState->handCount[player];
		newDeckSize = tState->deckCount[player];

		//the new treasure counts...
		//in hand:
		for(h=0; h<newHandSize; h++) {
			if (tState->hand[player][h] == copper) {
				nhTreasCardCount++;
				nhCoppCount++;
			} else if (tState->hand[player][h] == silver) {
				nhTreasCardCount++;
				nhSilvCount++;
			} else if (tState->hand[player][h] == gold) {
				nhTreasCardCount++;
				nhGoldCount++;
			}
		}
		//in deck:
		for(d=0; d<newDeckSize; d++) {
			if (tState->deck[player][d] == copper) {
				ndTreasCardCount++;
				ndCoppCount++;
			} else if (tState->deck[player][d] == silver) {
				ndTreasCardCount++;
				ndSilvCount++;
			} else if (tState->deck[player][d] == gold) {
				ndTreasCardCount++;
				ndGoldCount++;
			}
		}
		
		//check that up to 2 treasure cards in deck (if existent) were added to hand
		if (dTreasCardCount == 0){
			if (ndTreasCardCount == dTreasCardCount) {
				printf("0 cards added\n");
			} else {
				printf("Test failed, 0 cards should have been added.\n");
				return;
			}
		}
		if (dTreasCardCount == 1){
			if (nhTreasCardCount == hTreasCardCount+1) {
				printf("1 card added\n");
			} else {
				printf("Test failed, 1 card should have been added.\n");
				return;
			}
		}
		if (dTreasCardCount == 2){
			if (nhTreasCardCount == hTreasCardCount+2) {
				printf("2 cards added\n");
			} else {
				printf("Test failed, 2 cards should have been added.\n");
				return;
			}
		}
		//check that no more than 2 treasure cards were added to hand
		if (nhTreasCardCount > (hTreasCardCount + 2)) {
			printf("Test failed, more than 2 cards were added to hand.");
			return;
		}
		
		printf("After play: %d card hand with %d C, %d S, %d G.\n\n", newHandSize, nhCoppCount, nhSilvCount, nhGoldCount);

	//end loop
	}
	printf("Adventurer tests passed.\n");
	return;
}

